package org.example.admin.service.impl;

import cn.hutool.core.util.StrUtil;
import org.example.admin.constant.RedisConstants;
import org.example.admin.dao.UserDao;
import org.example.admin.service.LoginService;
import org.example.admin.service.MenuService;
import org.example.admin.service.RoleService;
import org.example.admin.dto.LoginDto;
import org.example.admin.vo.UserVo;
import org.example.core.constant.TokenConstants;
import org.example.core.exception.ExceptionCode;
import org.example.core.exception.auth.AuthorizeException;
import org.example.core.utils.R;
import org.example.core.to.LoginUser;
import org.example.redis.service.RedisService;
import org.example.security.handler.SecurityHandler;
import org.example.security.service.TokenService;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.security.crypto.bcrypt.BCryptPasswordEncoder;
import org.springframework.stereotype.Service;

import java.util.HashMap;
import java.util.Map;
import java.util.Set;

/**
 * @author 小杰_cc
 * @version 1.0
 */
@Service
public class LoginServiceImpl implements LoginService {

    @Autowired
    private RedisService redisService;

    @Autowired
    private UserDao userDao;

    @Autowired
    private RoleService roleService;

    @Autowired
    private MenuService menuService;

    @Autowired
    private TokenService tokenService;

    @Override
    public R<String> login(LoginDto loginDto) {

        // 获取验证码
        String redisCode = redisService.getObject(RedisConstants.CAPTCHA_KEY + loginDto.getCaptchaKey());
        // 验证码为空
        if (StrUtil.isBlank(redisCode)){
            return R.error("验证码已过期请更换验证码");
        }
        // 对比验证码
        if (!redisCode.equalsIgnoreCase(loginDto.getCaptchaText())){
            return R.error("验证码错误");
        }
        // 查询登录用户
        UserVo userVo = userDao.getUserByUserName(loginDto.getUsername());
        // 用户不存在
        if (userVo==null){
            return R.error("用户不存在");
        }
        // 账号状态
        if (userVo.getStatus() == 1){
            return R.error("抱歉您的账号已被禁用");
        }
        // 密码校验
        BCryptPasswordEncoder encoder = new BCryptPasswordEncoder();
        boolean matches = encoder.matches(loginDto.getPassword(), userVo.getPassword());
        if (!matches){
            return R.error("密码输入错误");
        }
        // 删除验证码
        redisService.deleteObject(RedisConstants.CAPTCHA_KEY + loginDto.getCaptchaKey());
        // 获取用户角色
        Set<String> roles = roleService.getUserRoles(userVo);
        // 获取权限
        Set<String> permissions = menuService.userPermissions(userVo);
        LoginUser loginUser = new LoginUser();
        loginUser.setId(userVo.getId());
        loginUser.setUsername(userVo.getUsername());
        loginUser.setRoles(roles);
        loginUser.setPermissions(permissions);

        // 返回token信息;
        return R.ok(tokenService.createUserToken(loginUser));
    }


    @Override
    public String refreshToken() {
        // 解析出数据
        String userId = SecurityHandler.getData().get(TokenConstants.USER_ID);
        String username = SecurityHandler.getData().get(TokenConstants.USER_NAME);
        // 刷新权限信息
        boolean refresh = tokenService.refreshUserCache(userId);
        if (!refresh){
            // 权限过期
            throw new AuthorizeException(ExceptionCode.UNAUTHORIZED.getCode(),ExceptionCode.UNAUTHORIZED.getMsg());
        }
        // 都成功生成新token返回
        return tokenService.refreshUserToken(userId, username);
    }

    @Override
    public Map<String, Object> getUserInfo() {
        String userId = SecurityHandler.getData().get(TokenConstants.USER_ID);
        HashMap<String, Object> map = new HashMap<>();
        if (StrUtil.isBlank(userId)){
            return map;
        }
        UserVo userVo = userDao.detail(Long.parseLong(userId));
        // 获取角色
        Set<String> roles = roleService.getUserRoles(userVo);
        // 获取权限
        Set<String> permissions = menuService.userPermissions(userVo);
        userVo.setPassword(null);
        map.put("user",userVo);
        map.put("roles",roles);
        map.put("permissions",permissions);
        return map;
    }
}